using System;
using System.Collections;
using System.Collections.Generic;
using System.Html;
using System.Runtime.CompilerServices;
using ThemeChain;

namespace Nsb.Classes
{
    [IgnoreNamespace]
    public static class Undo
    {
        private static int _st;
        private static int _at;
        private static int _was;
        private static int _max;
        private const int Max = 10;
        public const bool BypassUndo = true;
        public const bool AllowUndo = false;

        private static string Key(string dbKey, int idx)
        {
            return ThemeBase.UndoKey + "." + dbKey + "." + idx;
        }

        private static string IdxKey(string dbKey)
        {
            return ThemeBase.UndoKey + "." + dbKey + "#idxs";
        }

        private static void LoadIndexes(string dbKey)
        {
            Dictionary<string, int> sv = (Dictionary)Storage.GetSession(IdxKey(dbKey));
            if (Script.IsValue(sv))
            {
                _st = sv["_st"];
                _at = sv["_at"];
                _max = sv["_max"];
            }
            else
            {
                _st = _at = 0;
                _max = Max;
            }
        }

        private static void SaveIndexes(string dbKey)
        {
            Storage.SetSession(IdxKey(dbKey), new Dictionary("_st", _st, "_at", _at, "_max", _max));
        }
        public static object Prior(string dbKey)
        {
            LoadIndexes(dbKey);
            _was = _at;
            _at = _at <= 0 ? _max : _at - 1;
            if (_at == _st)
            {
                _at = _was;
                return null;
            }
            string key = Key(dbKey, _at);
            object content = Storage.GetSession(key);
            if (!Script.IsValue(content))
            {
                _at = _was;
                return null;
            }
            SaveIndexes(dbKey);
            return content;
        }

        public static object Next(string dbKey)
        {
            LoadIndexes(dbKey);
            _was = _at;
            if (_at == _st)
            {
                _at = _was;
                return null;
            }
            _at = _at >= _max ? 0 : _at + 1;
            string key = Key(dbKey, _at);
            object content = Storage.GetSession(key);
            if (!Script.IsValue(content))
            {
                _at = _was;
                return null;
            }
            SaveIndexes(dbKey);
            return content;
        }

        public static void Save(object buff, string dbKey)
        {
            LoadIndexes(dbKey);
            Purge(dbKey);
            SaveThis(buff, dbKey);
        }

        public static void Start(object buff, string dbKey)
        {
            if (!Script.IsValue(Storage.GetSession(IdxKey(dbKey))))
            {
                Clear(dbKey);
                SaveThis(buff, dbKey);
            }
        }

        private static void SaveThis(object buff, string dbKey)
        {
            _at = _st = _at >= _max ? 0 : _at + 1;
            string key = Key(dbKey, _at);
            Storage.SetSession(key, buff);
            SaveIndexes(dbKey);
        }

        public static bool HasPrior(string dbKey)
        {
            return Has(Prior(dbKey), dbKey);
        }

        public static bool HasNext(string dbKey)
        {
            return Has(Next(dbKey), dbKey);
        }

        private static bool Has(object tst, string dbKey)
        {
            _at = _was;
            SaveIndexes(dbKey);
            return Script.IsValue(tst);
        }

        private static void Purge(string dbKey)
        {
            _was = _at;

            while (_at != _st)
            {
                _at = _at >= _max ? 0 : _at + 1;
                string key = Key(dbKey, _at);
                // Because IE8 and before have broken RemoveItem
                try
                {
                    Window.SessionStorage.RemoveItem(key);
                }
                catch
                {
                    Window.SessionStorage[key] = "";
                }

            }
            _at = _st = _was;
        }

        private static void Clear(string dbKey)
        {
            ClearFor(ThemeBase.UndoKey + "." + dbKey + ".");
        }

        public static void ClearAll()
        {
            ClearFor(ThemeBase.UndoKey + ".");
        }

        private static void ClearFor(string key)
        {
            _st = _at = 0;
            _max = Max;
            List<string> keys = new List<string>();
            for (int i = 0; i < Window.SessionStorage.Length; i++)
            {
                if (Window.SessionStorage.GetKey(i).Substr(0, key.Length) == key)
                {
                    keys.Add(Window.SessionStorage.GetKey(i));
                }
            }
            foreach (string k in keys)
            {
                // Because IE8 and before have broken RemoveItem
                try
                {
                    Window.SessionStorage.RemoveItem(k);
                }
                catch
                {
                    Window.SessionStorage[k] = "";
                }
            }
        }
    }
}
